package libra.sentinelTest.controller;

import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;


/**
 * Sentinel - Flow流控测试Controller
 */
@RestController
@RequestMapping("flow")
public class FlowController {
	String from = getClass().getSimpleName();
	
	/************************** 阈值类型测试 ******************************/
	/**
	 * 测试[阈值类型(QPS)]
	 * 	流控模式：直接(默认)
	 * 	流控效果：快速失败(默认)
	 */
	@RequestMapping("testQPS")
	public Object testQPS() {
		return Map.of("from", from, "method", "testQPS");
	}
	
	/**
	 * 测试[阈值类型(线程数)]
	 * 	流控模式：直接(默认)
	 * 	流控效果：快速失败(默认)
	 */
	@RequestMapping("testThread")
	public Object testThread() {
		return Map.of("from", from, "method", "testThread");
	}
	
	
	/************************** 流控模式测试 ******************************/
	/**
	 * 测试[流控模式(关联)]
	 * 	阈值类型：QPS
	 * 	流控效果：快速失败(默认)
	 * 当关联资源'strategyRelate'达到"阈值类型"峰值时，则限流当前流控资源'testStrategyRelate'
	 */
	// 测试"流控模式(关联)"的被限流资源
	@RequestMapping("testStrategyRelate")
	public Object testStrategyRelate() {
		return Map.of("from", from, "method", "testStrategyRelate");
	}
	// 测试"流控模式(关联)"的关联资源
	@RequestMapping("strategyRelate")
	public Object strategyRelate() {
		return Map.of("from", from, "method", "strategyRelate");
	}
	
	@Autowired
	ApplicationContext ac;
	/**
	 * 测试[流控模式(链路)]
	 * 	阈值类型：QPS
	 * 	流控效果：快速失败(默认)
	 * 当限流方法资源'strategyChain'触发限流阈值，且调用其的入口资源为我们指定的"testStrategyChain_2"
	 * 则对限流方法资源'strategyChain'进行限流
	 */
	// 测试"流控模式(链路)"的入口资源_1
	@RequestMapping("testStrategyChain/1")
	public Object testStrategyChain_1( HttpServletResponse resp ) {
		ac.getBean(FlowController.class).strategyChain(resp);
		return Map.of("from", from, "method", "testStrategyChain_1");
	}
	// 测试"流控模式(链路)"的入口资源_2
	@RequestMapping("testStrategyChain/2")
	public Object testStrategyChain_2( HttpServletResponse resp ) {
		ac.getBean(FlowController.class).strategyChain(resp);
		return Map.of("from", from, "method", "testStrategyChain_2");
	}
	// 测试"流控模式(链路)"的限流资源[普通被调用方法]
	@SentinelResource(value = "strategyChain", blockHandler = "strategyChain_BlockExec" )
	public Object strategyChain( HttpServletResponse resp ) {
		return Map.of("from", from, "method", "strategyChain");
	}
	// blockExec函数，原方法调用被限流/降级/系统保护的时候调用
	public Object strategyChain_BlockExec( HttpServletResponse resp, BlockException ex) {
		resp.setStatus(429);
		return  Map.of("from", from, "method", "strategyChain_BlockExec");
	}
	
	
	/************************** 流控效果测试 ******************************/
	/**
	 * 测试[流控效果(WarmUp预热)]
	 * 	阈值类型：QPS
	 * 	流控模式：直接(默认)
	 * 当限流资源'testBehaviorWarmUp'触发限流阈值
	 * 	Sentinel会先按照['单机阈值'/'ClodFactor(默认值:3)']的取整结果，对限流资源'testBehaviorWarmUp'进行限流
	 * 	在经过'预热时长'时间后，会逐步将限流阈值放宽到我们的预设置对限流资源'testBehaviorWarmUp'进行限流
	 */
	@RequestMapping("testBehaviorWarmUp")
	public Object testBehaviorWarmUp( HttpServletResponse resp ) {
		return Map.of("from", from, "method", "testBehaviorWarmUp");
	}
	
	/**
	 * 测试[流控效果(RateLimiter排队等待)]
	 * 	阈值类型：QPS(仅支持QPS)
	 * 	流控模式：直接(默认)
	 * 当限流资源'testBehaviorRateLimiter'触发限流阈值
	 * 	Sentinel会将剩余待处理请求进行排队，等待处理
	 * 		如果请求等待时长 < '超时时间'，则该请求会被放行，正常执行返回
	 * 		如果请求等待时长 ≥ '超时时间'，则该请求仍会被流控限流
	 */
	@RequestMapping("testBehaviorRateLimiter")
	public Object testBehaviorRateLimiter( HttpServletResponse resp ) {
		return Map.of("from", from, "method", "testBehaviorRateLimiter");
	}
}
